/*
 * DevilSemantic.h
 *
 *  Created on: Oct 18, 2012
 *      Author: wtao
 */

#ifndef DEVILSEMANTIC_H_
#define DEVILSEMANTIC_H_

#include "CxxUtils.h"
#include "LangUtils.h"
#include "DoOpArithmetic.h"
#include "DoOpCoordinateMatrix.h"
#include "DoOpBoolean.h"
#include "DoOpDictionary.h"
#include "DoOpFont.h"
#include "DoOpGrphStateDI.h"
#include "DoOpPackedArray.h"
#include "DoOpPath.h"
#include "DoOpString.h"
#include "DoOpArray.h"
#include "DoOpControl.h"
#include "DoOpDeviceOutput.h"
#include "DoOpFileRes.h"
#include "DoOpGrphStateDD.h"
#include "DoOpMiscellaneous.h"
#include "DoOpPaint.h"
#include "DoOpStack.h"
#include "DoOpType.h"
#include <istream>
#include <ostream>

using namespace std;

//for gdb debugging
const char * ptoken(CRefPtr< _DoObject > token);
const char * ptoken(_DoObject &token);
//end for gdb debugging

class DevilParser 
{
protected:
	DevilParser(const DevilParser&);
	DevilParser& operator=(const DevilParser&);
		
	int parseComment(istream &is, onTokenListener &listener);
	
	int parseName(int currChar, istream &is, onTokenListener &listener);
	
	int parseProcedure(istream &is, onTokenListener &listener);
	
	int parseNumber(int currChar, istream &is, onTokenListener &listener);
	
	int parseLiteral(istream &is, onTokenListener &listener);
	
	int beginArray(istream &is, onTokenListener &listener);
	
	int endArray(istream &is, onTokenListener &listener);
	
	int parseLiteralHex(int currChar, istream &is, onTokenListener &listener);
	
	int parseDictionary(istream &is, onTokenListener &listener);
	
	void addLine();

	int mLineNo;
	
public:
	DevilParser();
	~DevilParser() {}
	
	void parse(istream &is, onTokenListener& state);
	
	int parseLiteralAscii85(istream &is, onTokenListener &listener);
};

class DoDictionaryStack : public _DoStack
{
protected:
	vector< CRefPtr< _DoObject> > find(CRefPtr< _DoObject > key);

	CRefPtr< _DoObject >  _systemdict;
	
	CRefPtr< _DoObject >  _globaldict;
	
	CRefPtr< _DoObject >  _userdict;

public:
	DoDictionaryStack();

	CRefPtr< _DoObject > findDict(CRefPtr< _DoObject > key);

	CRefPtr< _DoObject > lookup(CRefPtr< _DoObject > key, DevilSemantic &state);

	void put(CRefPtr< _DoObject > key, CRefPtr< _DoObject > value);
	
	CRefPtr< _DoObject > globaldict();
	
	CRefPtr< _DoObject > userdict();
	
	CRefPtr< _DoObject > systemdict();
};

class DevilSemantic : public onTokenListener
{
protected:
	DevilSemantic(const DevilSemantic&);
	DevilSemantic& operator=(const DevilSemantic&);
	
//for gdb debugging
	const char * pstack();
	const char * pdictstack();
//end for gdb debugging

	void _debug_dump(CRefPtr< _DoObject > token);

	std::istream *mStdInput;

	CRefPtr < _DoObject > mGraphic;
	
	_DoStack mStackOp;

	DoDictionaryStack mStackDict;

	DoDictionary mFontDict;
	
	DevilParser mParser;
public:
	DevilSemantic();
	virtual ~DevilSemantic();

	void setStandardInput(std::istream *pin) {
		mStdInput = pin;
	}
	
	void setGraphicState(CRefPtr < _DoObject > gs) {
		mGraphic = gs;
	}
	
	_DoStack& getOpStack(){
		return mStackOp;
	}

	DoDictionaryStack& getDictStack() {
		return mStackDict;
	}
	
	DoDictionary& getFontDict() {
		return mFontDict;
	}
	
	DevilParser& getLexParser() {
		return mParser;
	}
	
	SkiaGraphicState * getGraphicState() {
		return dynamic_cast< SkiaGraphicState * >(mGraphic.get());
	}
	
	void outputDebugString(const std::string& str);
	
	CRefPtr< _DoObject > currentFile() {
		return CRefPtr< _DoObject >(new DoFile(*mStdInput));
	}
	
	void parse();
	
	virtual void onToken(CRefPtr< _DoObject > token);

	virtual onTokenListener::eContinueParse onChar(int currChar);
};

#endif /* DEVILSEMANTIC_H_ */
